package com.xmut.mall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.xmut.mall.product.service.CategoryBrandRelationService;
import com.xmut.mall.product.utils.RespBean;
import com.xmut.mall.product.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.mall.product.utils.PageUtils;
import com.xmut.mall.product.utils.Query;

import com.xmut.mall.product.dao.CategoryDao;
import com.xmut.mall.product.entity.CategoryEntity;
import com.xmut.mall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    private CategoryDao categoryDao;

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 查出所有的分类以及子分类，以树形结构组装起来返回给前端
     */
    @Cacheable(value = "CategoryTree", key = "#root.methodName")
    @Override
    public List<CategoryEntity> listWithTree() {
        // 查出所有分类
        List<CategoryEntity> entities = categoryDao.selectList(null);
//        // 组装称树形的结构
        List<CategoryEntity> Menu = entities.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentCid() == 0;
        }).map((menu) -> {
            menu.setChildren(getChildrens(menu, entities));
            return menu;
        }).sorted((menu1, menu2) -> {
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());


        return Menu;
    }

    @Override
    public void removeMenuByIds(List<Long> asList) {
        // 检查菜单是否被引用

        // 此处不会真的删除 而是使用逻辑删除
        baseMapper.deleteBatchIds(asList);
    }

    @Override
    public Long[] findCatelogPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        List<Long> parentPath = findParentPath(catelogId, paths);

        Collections.reverse(parentPath);

        return parentPath.toArray(new Long[parentPath.size()]);
    }

    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
    }

    /**
     * 获取商品的二级分类和三级分类
     *
     * @return
     */
    @Cacheable(value = "category", key = "#root.methodName")
    @Override
    public Map<String, List<Catelog2Vo>> getIndexCateLevel2andLevel3() {
        List<CategoryEntity> selectList = baseMapper.selectList(null);
        // 获取一级分类
        List<CategoryEntity> level1Categorys = getParent_cid(selectList, 0L);
        //2、封装数据
        Map<String, List<Catelog2Vo>> parent_cid = level1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
            //1、每一个的一级分类，查到这个一级分类的二级分类
            List<CategoryEntity> categoryEntities = getParent_cid(selectList, v.getCatId());
            //2、封装上面面的结果
            List<Catelog2Vo> catelog2Vos = null;
            if (categoryEntities != null) {
                catelog2Vos = categoryEntities.stream().map(l2 -> {
                    Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName());
                    //1、找当前二级分类的三级分类封装成vo
                    List<CategoryEntity> level3Catelog = getParent_cid(selectList, l2.getCatId());
                    if (level3Catelog != null) {
                        List<Catelog2Vo.Catelog3Vo> collect = level3Catelog.stream().map(l3 -> {
                            //2、封装成指定格式
                            Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName());
                            return catelog3Vo;
                        }).collect(Collectors.toList());
                        catelog2Vo.setCatalog3List(collect);
                    }
                    return catelog2Vo;
                }).collect(Collectors.toList());
            }


            return catelog2Vos;
        }));

        return parent_cid;
    }

    /**
     * 查出所有的一级分类
     *
     * @return
     */
    @Cacheable(value = "category", key = "#root.methodName")
    @Override
    public List<CategoryEntity> getCateLogLevel1() {
        // 1及分类的父id号为0
        return this.baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
    }

    /**
     * 获取全部的分类
     *
     * @return
     */
    @Cacheable(value = "category", key = "#root.methodName")
    @Override
    public List<CategoryEntity> getAllCate() {
        return this.baseMapper.selectList(null);
    }

    /**
     * 根据cateId获取它的父分类将其组合起来
     */
    @Override
    public List<CategoryEntity> getCateParentAndMerge(Long catalogId) {
        // 要返回的总组合
        List<CategoryEntity> merge = new ArrayList<>();

        // 获取全部分类
        List<CategoryEntity> allCate = this.getAllCate();

        // 先找出当前catalogId对应的单个cate
        CategoryEntity nowCate = allCate.stream().filter(item -> {
            return item.getCatId().equals(catalogId);
        }).findAny().orElse(null);
        merge.add(nowCate);

        Integer flag = nowCate.getCatLevel();
        Long nowParentId = nowCate.getParentCid();
        // 查找它的父cate并且合并到list中最后一起返回
        while (flag != 1) {
            for (CategoryEntity item : allCate) {
                if (item.getCatId().equals(nowParentId)) {
                    merge.add(item);
                    flag = item.getCatLevel();
                    nowParentId = item.getParentCid();
                }
            }
        }

        return merge;
    }

    /**
     * 添加分类
     *
     * @param vo
     * @return
     */
    @CacheEvict(value = "CategoryTree", key = "'getCateTree'")
    @Override
    public RespBean addCate(AddCateVo vo) {
        CategoryEntity category = new CategoryEntity();
        category.setName(vo.getName());
        category.setIcon(vo.getImage());
        category.setCatLevel(vo.getCatLevel());
        category.setParentCid(vo.getParentId());
        category.setShowStatus(vo.getShowStatus());
        category.setSort(vo.getSortOrder());

        boolean save = this.save(category);
        if (save) {
            return RespBean.success("添加成功");
        } else {
            return RespBean.error("添加失败,请重试");
        }

    }

    /**
     * 获取三级分类树
     *
     * @return
     */
    @Cacheable(value = "CategoryTree",key = "'getCateTree'")
    @Override
    public List<CategoryEntity> getCateTree() {
        // 先查出全部的分类
        List<CategoryEntity> all = this.list();
        // 过滤出全部的一级分类
        List<CategoryEntity> cateLevel1 = all.stream().filter(i -> i.getCatLevel() == 1).collect(Collectors.toList());

        for (CategoryEntity level1Item : cateLevel1) {
            // 查询该以及分类对应的二级分类
            List<CategoryEntity> cateLevel2 = all.stream().filter(level2Item->{
                // 返回所有结果里 是二级分类 并且 父id和当前正在遍历的leve1的id相同的
                return level2Item.getCatLevel() ==2 && level2Item.getParentCid().equals(level1Item.getCatId());
            }).map(level2->{
                // 这里的全都是当前一级分类的二级分类
                // 查询当前二级分类对应的三级分类
                List<CategoryEntity> level3Collection = all.stream().filter(level3Item -> {
                    // 因为分类最多就三级 所以不往下找了
                    return level3Item.getCatLevel() == 3 && level3Item.getParentCid().equals(level2.getCatId());
                }).collect(Collectors.toList());
                // 给level3 的children一个[]值 如果不赋值将会是null 前端判空会报错
                for (CategoryEntity category3 : level3Collection) {
                    category3.setChildren(new ArrayList<>());
                }
                level2.setChildren(level3Collection); // 设置三级分类
                return level2;
            }).collect(Collectors.toList());
            // 给每个一级分类设置二级分类
            level1Item.setChildren(cateLevel2);
        }
        //组装完成 返回
        return cateLevel1;
    }

    /**
     * 编辑分类信息
     * @param vo
     * @return
     */
    @CacheEvict(value = "CategoryTree", key = "'getCateTree'")
    @Override
    public RespBean editCate(EditCateVo vo) {
        CategoryEntity category = new CategoryEntity();
        category.setCatId(vo.getId());
        category.setCatLevel(vo.getCatLevel());
        category.setIcon(vo.getImage());
        category.setName(vo.getName());
        category.setParentCid(vo.getParentId());
        category.setShowStatus(vo.getShowStatus());
        category.setSort(vo.getSortOrder());

        // 修改
        boolean b = this.updateById(category);
        if(b){
            return RespBean.success("修改成功");
        }else {
            return RespBean.error("修改失败");
        }
    }

    /**
     * 禁用分类
     * @param cateId
     * @return
     */
    @Override
    @CacheEvict(value = "CategoryTree", key = "'getCateTree'")
    public RespBean disableCate(Long cateId) {
        boolean update = this.update(new UpdateWrapper<CategoryEntity>().eq("cat_id", cateId).set("show_status", 0));
        if(update){
            return RespBean.success("禁用成功");
        }else {
            return RespBean.error("禁用失败");
        }

    }

    /**
     * 启用分类
     * @param cateId
     * @return
     */
    @CacheEvict(value = "CategoryTree", key = "'getCateTree'")
    @Override
    public RespBean enableCate(Long cateId) {
        boolean update = this.update(new UpdateWrapper<CategoryEntity>().eq("cat_id", cateId).set("show_status", 1));
        if(update){
            return RespBean.success("启用成功");
        }else {
            return RespBean.error("启用失败");
        }
    }

    @Override
    public RespBean getCateTreeById(Long cateId) {
        List<CategoryEntity> list = this.list(new QueryWrapper<CategoryEntity>().eq("parent_cid", cateId));
        return RespBean.success("获取成功",list);

    }

    /**
     * 获取分类选择组件的数据结果
     * @return
     */
    @Override
    public RespBean getCateTreeComponent() {
        List<CategoryEntity> cateTree = getCateTree();

        // 组装工属具
        List<CateComponentVo> result = cateTree.stream().map(item -> {
            // 第一级分类的遍历

            List<CateComponentVo> cateLevel2 = item.getChildren().stream().map(level2 -> {
                // 第二级的遍历
                CateComponentVo vo = new CateComponentVo();
                vo.setId(level2.getCatId());
                vo.setTitle(level2.getName());
                vo.setCatLevel(level2.getCatLevel());
                vo.setExpand(false);
                // 第三极的遍历 这一集不需要children和expand了
                List<CateComponentVo> cateLvele3 = level2.getChildren().stream().map(level3 -> {
                    CateComponentVo vo3 = new CateComponentVo();
                    vo3.setId(level3.getCatId());
                    vo3.setTitle(level3.getName());
                    vo3.setCatLevel(level3.getCatLevel());
                    return vo3;
                }).collect(Collectors.toList());
                vo.setChildren(cateLvele3);
                return vo;
            }).collect(Collectors.toList());


            CateComponentVo vo = new CateComponentVo();
            vo.setId(item.getCatId());
            vo.setTitle(item.getName());
            vo.setExpand(false);
            vo.setCatLevel(item.getCatLevel());
            vo.setChildren(cateLevel2);

            return vo;
        }).collect(Collectors.toList());
        return RespBean.success("获取成功",result);

    }

    /**
     * 获取适配前端的Cascader组件的分类树
     * @return
     */
    @Override
    public RespBean getCateByCascader() {
        List<CategoryEntity> cateTree = getCateTree();

        // 组装工属具
        List<CateCascaderVo> result = cateTree.stream().map(item -> {
            // 第一级分类的遍历

            List<CateCascaderVo> cateLevel2 = item.getChildren().stream().map(level2 -> {
                // 第二级的遍历
                CateCascaderVo vo = new CateCascaderVo();
                vo.setValue(level2.getCatId());
                vo.setLabel(level2.getName());
                vo.setCatLevel(level2.getCatLevel());
//                vo.setExpand(false);
                // 第三极的遍历 这一集不需要children和expand了
                List<CateCascaderVo> cateLvele3 = level2.getChildren().stream().map(level3 -> {
                    CateCascaderVo vo3 = new CateCascaderVo();
                    vo3.setValue(level3.getCatId());
                    vo3.setLabel(level3.getName());
                    vo3.setCatLevel(level3.getCatLevel());
                    return vo3;
                }).collect(Collectors.toList());
                vo.setChildren(cateLvele3);
                return vo;
            }).collect(Collectors.toList());


            CateCascaderVo vo = new CateCascaderVo();
            vo.setValue(item.getCatId());
            vo.setLabel(item.getName());
//            vo.setExpand(false);
            vo.setCatLevel(item.getCatLevel());
            vo.setChildren(cateLevel2);

            return vo;
        }).collect(Collectors.toList());




        return RespBean.success("获取成功",result);


    }


    private List<Long> findParentPath(Long catelogId, List<Long> paths) {
        // 收集当前节点id
        paths.add(catelogId);
        CategoryEntity category = this.getById(catelogId);
        if (category.getParentCid() != 0) {
            findParentPath(category.getParentCid(), paths);
        }
        return paths;
    }

    // 递归查找所有菜单的子菜单
    private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {

        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid() == root.getCatId();
        }).map(categoryEntity -> {
            // 找到子菜单
            categoryEntity.setChildren(getChildrens(categoryEntity, all));
            return categoryEntity;
        }).sorted((menu1, menu2) -> {
            // 进行排序
            // 因为 sort可能为null 所以加一个判断
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());

        return children;
    }

    private List<CategoryEntity> getParent_cid(List<CategoryEntity> selectList, Long parent_cid) {
//        return baseMapper.selectList(new QueryWrapper<CategoryEntity>()
//                .eq("parent_cid", v.getCatId()));
        List<CategoryEntity> collect = selectList.stream().filter(item -> {
            return item.getParentCid() == parent_cid;
        }).collect(Collectors.toList());
        return collect;
    }

}